package com.home.oss.service;

import com.home.base.core.context.BaseContextHandler;
import com.home.base.core.framework.msg.ServerResponse;
import com.home.common.enums.OssFolderEnum;
import com.home.common.framework.core.entity.EntityUtils;
import com.home.oss.config.FileConfig;
import com.home.oss.entity.OssBizFile;
import com.home.oss.entity.OssBizFileMd5;
import com.home.oss.factory.FileFactoryServer;
import com.home.oss.mapper.BizFileMapper;
import com.home.oss.mapper.BizFileMd5Mapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;

/**
 * Description:
 * Created by 王大宸 on 2020-10-15 21:48
 * Created with IntelliJ IDEA.
 */
@Service
public class LocalUploadServer extends FileFactoryServer {
    private static final Logger logger = LoggerFactory.getLogger(LocalUploadServer.class);
    private static FileConfig fileConfig;
    private static BizFileMd5Mapper bizFileMd5Mapper;
    private static BizFileMapper bizFileMapper;

    @Autowired
    public void setBaseFamilyMapper(FileConfig fileConfig) {
        LocalUploadServer.fileConfig = fileConfig;
    }

    @Autowired
    public void setBizFileMd5Mapper(BizFileMd5Mapper bizFileMd5Mapper) {
        LocalUploadServer.bizFileMd5Mapper = bizFileMd5Mapper;
    }

    @Autowired
    public void setBizFileMapper(BizFileMapper bizFileMapper) {
        LocalUploadServer.bizFileMapper = bizFileMapper;
    }

    /***
     * 功能说明：本地文件上传方法
     *
     * @author 王大宸
     * @date 2020/10/15 22:02
     * @param file 文件
     * @param type 文件类型
     * @return com.home.common.framework.msg.ServerResponse<com.home.oss.entity.BaseBizFileMd5>
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServerResponse<OssBizFile> upload(MultipartFile file, String type) {
        try {
            if (StringUtils.isEmpty(file.getOriginalFilename())) {
                logger.error(BaseContextHandler.getName() + "上传文件为空");
                return ServerResponse.errMsg("请选择需要上传的文件");
            }
            long size = file.getSize();
            String md5Hex = DigestUtils.md5Hex(file.getInputStream());
            OssBizFileMd5 fileMd5 = bizFileMd5Mapper.getByMd5(md5Hex);
            OssBizFile ossBizFile = null;
            if (null != fileMd5) {
                /* 文件入库 */
                ossBizFile = new OssBizFile();
                ossBizFile.setBizMd5(md5Hex);
                ossBizFile.setRealPath(fileMd5.getRealPath());
                ossBizFile.setUrl(fileMd5.getUrl());
                ossBizFile.setFileSize(size);
                ossBizFile.setBizType(type);
                ossBizFile.setFileName(file.getOriginalFilename());
                ossBizFile.setFileFormat(file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")));
                EntityUtils.toCreateEntity(ossBizFile);
                bizFileMapper.insert(ossBizFile);
                return ServerResponse.okData(ossBizFile);
            }

            // 获取文件上传文件夹
            String folder = OssFolderEnum.getFolderByType(type);
            // 文件上传
            String src = fileUpload(folder, file);
            // 文件网络地址
            String url = fileConfig.getHttp() + "upload/" + src.replace(fileConfig.getUploadPath(), "");


            // 文件 MD5 入库
            OssBizFileMd5 ossBizFileMd5 = new OssBizFileMd5();
            ossBizFileMd5.setFileName(file.getOriginalFilename());
            ossBizFileMd5.setId(EntityUtils.getId());
            ossBizFileMd5.setMd5(md5Hex);
            ossBizFileMd5.setUrl(url);
            ossBizFileMd5.setRealPath(src);
            ossBizFileMd5.setFileFormat(file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")));
            ossBizFileMd5.setFileSize(size);
            ossBizFileMd5.setCreateTime(LocalDateTime.now());
            bizFileMd5Mapper.insert(ossBizFileMd5);

            /* 文件入库 */
            ossBizFile = new OssBizFile();
            ossBizFile.setBizMd5(md5Hex);
            ossBizFile.setRealPath(ossBizFileMd5.getRealPath());
            ossBizFile.setUrl(ossBizFileMd5.getUrl());
            ossBizFile.setFileSize(size);
            ossBizFile.setBizType(type);
            ossBizFile.setFileName(file.getOriginalFilename());
            ossBizFile.setFileFormat(file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")));
            EntityUtils.toCreateEntity(ossBizFile);
            bizFileMapper.insert(ossBizFile);

            return ServerResponse.okData(ossBizFile);
        } catch (IOException e) {
            logger.error("获取文件 MD5 失败: ", e);
            return ServerResponse.errMsg("上传失败");
        } catch (Exception e) {
            logger.error("文件上传失败: ", e);
            return ServerResponse.errMsg("上传失败");
        }
    }


    /***
     * 功能说明：文件上传工具类
     *
     * @author 王大宸
     * @date 2020/10/15 22:09
     * @param folder  存放文件夹
     * @param file    文件
     * @return java.lang.String
     */
    public String fileUpload(String folder, MultipartFile file) throws IOException {
        String filePath = fileConfig.getUploadPath() + folder + "/" + LocalDate.now().getYear() + "/" + LocalDate.now().getMonthValue() + "/";
        //如果文件路径不存在 创建路径
        File fileDir = new File(filePath);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }
        //文件名称,防止名称重复,用当前时间命名
        String fileName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + EntityUtils.getId();
        String fileType = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf("."));
        fileName = fileName + fileType;

        File uploadFile = new File(filePath, fileName);
        file.transferTo(uploadFile);

        // String src = filePath.substring(filePath.lastIndexOf("/static")) + fileName;
        String src = filePath + fileName;
        logger.info("文件上传成功: " + src);
        return src;
    }
}
